import json
import datetime
from .utils import PropertyDict


class Response:
    STATUS = {
        100: "Continue",
        101: "Switching Protocols",

        200: "OK",
        201: "Created",
        202: "Accepted",
        203: "Non-Authoritative Information",
        204: "No Content",
        205: "Reset Content",
        206: "Partial Content",

        300: "Multiple Choices",
        301: "Moved Permanently",
        302: "Found",
        303: "See Other",
        304: "Not Modified",
        305: "Use Proxy",
        306: "Unused",
        307: "Temporary Redirect",

        400: "Bad Request",
        401: "Unauthorized",
        402: "Payment Required",
        403: "Forbidden",
        404: "Not Found",
        405: "Method Not Allowed",
        406: "Not Acceptable",
        407: "Proxy Authentication Required",
        408: "Request Time-out",
        409: "Conflict",
        410: "Gone",
        411: "Length Required",
        412: "Precondition Failed",
        413: "Request Entity Too Large",
        414: "Request-URI Too Large",
        415: "Unsupported Media Type",
        416: "Requested range not satisfiable",
        417: "Expectation Failed",

        500: "Internal Server Error",
        501: "Not Implemented",
        502: "Bad Gateway",
        503: "Service Unavailable",
        504: "Gateway Time-out",
        505: "HTTP Version not supported"
    }

    def __init__(self,
                 body, status=200, charset="utf-8", content_type="text/html",

                 ):
        self.headers = PropertyDict()
        self.status_code = status
        self.body = body
        self.encode_body = b""
        self.headers.Allow = ""
        self.headers["Content-Encoding"] = ""
        self.headers["Content-Length"] = ""
        self.headers["Content-Type"] = "{}; charset={}"  # text/html charset=utf-8
        self.charset = charset
        self.content_type = content_type
        self.headers.Date = ""
        self.headers.Expires = ""
        self.headers["Set-Cookie"] = {}
        self.headers.Server = "Power0.0.1"
        self.headers.Refresh = ""
        self.headers.Location = ""
        self.status_message = ""
        self.headers.scheme = "HTTP/1.1"
        self.status(status)
        # self.set_ct("text/html", "charset=utf-8")

    def _get_headers(self):
        header_list = [self._first_line()]

        # 根据此时的body长度，设置content-length, 日期等
        self.set_content_length(self.encode_body)
        self.set_date()
        self.set_ct(self.content_type, self.charset)

        # TODO 此处没有传递一个列表对象进行extend，不知道可以不
        header_list.extend(f"{k}: {v}" for k, v in self.headers.items() if k != "body" and v)
        headers = "\r\n".join(header_list)
        return headers

    def set_charset(self, charset="utf-8"):
        self.charset = charset

    def set_content_type(self, content_type="text/html"):
        self.content_type = content_type

    def __str__(self):
        headers = self._get_headers()

        return headers + """\r\n\r\n{}""".format(self.body)

    def set_date(self):
        # Tue, 24 Nov 2020 10:54:20 GMT
        self.headers.Date = datetime.datetime.now().strftime("%a, %d %b %Y %H:%M:%S ") + "GMT"

    def set_content_length(self, body):
        self.headers["Content-Length"] = len(body)

    def set_headers(self, key, value, dicts, **kwargs):
        self.headers[key] = value
        self.headers.update(dicts)
        self.headers.update(kwargs)

    def status(self, value):
        self.status_message = self.STATUS.get(value, 200)
        self.status_code = value

    def _first_line(self):
        return "{} {} {}".format(self.headers.scheme, self.status_code, self.status_message)

    def set_cookies(self, k, v, dicts, **kwargs):
        self.headers.Set_Cookie[k] = v
        self.headers.Set_Cookie.update(dicts)
        self.headers.Set_Cookie.update(kwargs)

    def set_allow(self, method):
        self.headers.Allow = method

    def set_ct(self, *ct):
        self.content_type, self.charset = ct
        self.headers["Content-Type"] = self.headers["Content-Type"].format(*ct)

    def set_location(self, location):
        self.headers.Location = location

    def set_server(self, server):
        self.headers.Server = server

    def set_body(self, data):
        # if isinstance(data, )
        self.body = data
        self.encode_body = data.encode(self.charset)


class JsonResponse(Response):
    def __init__(self, dicts):
        super().__init__(self)
        self.set_content_type()
        self.set_body(json.dumps(dicts))

    def set_content_type(self, content_type="application/json; charset=utf-8"):
        self.headers["Content-Type"] = content_type
